﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Web;
using KPIS.GERP.Models;
using KPIS.GERP.Models.SYS;
using KPIS.GERP.Models.SYS.ViewModel;

namespace KPIS.GERP.WEB.GIMS.Class
{
    public static class SiteMenuUtility
    { 
        private static List<MenuItem> MenuItems { get; set; }
        private static List<UserRole> UserRoles { get; set; }

        public static List<MenuItem> GetMenu()
        {
            var currentUserId = GimsMembership.CurrentUserId;

            /* prevent change role and do not update menu in session
            if (HttpContext.Current.Session["UserFilteredMenus"] as List<MenuItem> != null)
            {
                return (List<MenuItem>) HttpContext.Current.Session["UserFilteredMenus"];
            }*/

            if (MenuItems == null || !MenuItems.Any())
            {
                MenuItems = LoadSiteMenuDatabase();
            }

            var userRoles = GetUserRoles(currentUserId);

            var result = FilterRole(MenuItems, userRoles);
            //HttpContext.Current.Session["UserFilteredMenus"] = result;

            return result;
        }

        public static List<UserRole> GetUserRoles(int userId)
        {
            if (UserRoles == null || !UserRoles.Any())
            {
                UserRoles = LoadUserRoleDatabase();
            }
            return UserRoles.Where(o => o.UserId == userId).ToList();
        }

        private static List<UserRole> LoadUserRoleDatabase()
        {
            var db = new GERPContext();
            return db.UserRoles.Where(o => o.RecordStatus != "D").ToList();
        }

        private static List<MenuItem> FilterRole(List<MenuItem> menuItems, List<UserRole> userRoles)
        {
            var user = GimsMembership.User;
            var result = new List<MenuItem>();
            foreach (var m in menuItems)
            {
                MenuItem header = m;
                if (IsInRole(m, user, userRoles))
                {
                    var listOfMenuItems = new List<MenuItem>();
                    foreach (var cm in m.MenuItems ?? new List<MenuItem>())
                    {
                        listOfMenuItems.Add(cm);
                    }
                    header.MenuItems = new List<MenuItem>();

                    foreach (var innerM in listOfMenuItems)
                    {
                        if (IsInRole(innerM, user, userRoles))
                        {
                            header.MenuItems.Add(innerM);
                        }
                    }

                    header.MenuItems = listOfMenuItems;
                    result.Add(header);
                }
            }
            return result;
        }

        public static bool IsInRole(MenuItem menuItem, User user, List<UserRole> userRoles)
        {
            if (user.IsAdmin) return true;

            var acceptedRoleIds = menuItem
                .Roles
                .Select(r => r.RoleId);

            return userRoles.Any(ur => acceptedRoleIds.Contains(ur.RoleId));
        }

        public static List<MenuItem> LoadSiteMenuDatabase()
        {
            var db = new GERPContext();
            var roles =
                db.Roles.Include("Permission").Where(o => o.RecordStatus != "D" && o.System == "WEBGIMS").ToList();
            var allNode = db.MenuItemsLists.Where(o => o.RecordStatus != "D" && o.SystemId == "WEBGIMS").ToList();
            var stLevelNodes = allNode.Where(o => o.UpperMenuItemId == null);
            var ndLevelNodes = allNode.Where(o => o.UpperMenuItemId.HasValue).ToArray();
            var result = new List<MenuItem>();

            // Loop on 1st level menu
            int i = 1;
            foreach (MenuItemsList topmenu in stLevelNodes)
            {
                result.Add(new MenuItem
                {
                    Text = topmenu.Name,
                    NavigateUrl = topmenu.Path,
                    Icon = topmenu.Icon,
                    SystemId =
                        (Models.SYS.ViewModel.SystemId)
                            Enum.Parse(typeof (Models.SYS.ViewModel.SystemId), topmenu.SystemId),

                    MenuItems =
                        ndLevelNodes
                            .Where(o => o.UpperMenuItemId == topmenu.MenuItemId)
                            .Select(j => new MenuItem
                            {
                                Text = j.Name,
                                NavigateUrl = j.Path,
                                Icon = j.Icon,
                                SystemId =
                                    (Models.SYS.ViewModel.SystemId)
                                        Enum.Parse(typeof (Models.SYS.ViewModel.SystemId), j.SystemId),
                                Roles =
                                    roles.Where(
                                        o => o.Permission != null && o.Permission.Any(p => p.MenuItemId == j.MenuItemId))
                                        .ToList()
                            }).ToList(),
                    Roles =
                        roles.Where(
                            o => o.Permission != null && o.Permission.Any(p => p.MenuItemId == topmenu.MenuItemId))
                            .ToList()


                });
            }

            MenuItems = result.OrderByDescending(o => o.Sequence).ToList();
            return MenuItems;
        }
    }
}